#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
typedef struct AList
{
	//定义一个列表类型结构，用不等长二维数组模拟列表类型结构 
	int m;//列表中子集的个数 
	int n;//所有子集中，最多元素的个数 
	int** alist;
	void (*InitAList)(struct AList* pls,int m,int n);
}AList;
void InitAList(struct AList* pls,int m,int n)
{
	pls->m = m;
	pls->n = n;
	pls->alist = (int**)malloc(sizeof(int*)*(pls->m));
	return;
}
void close(AList* pls)
{
	int i,j;
	for(i = 0;i < (pls->m);i++)
	{
		free((pls->alist)[i]);
	}
	free(pls->alist);
	return; 
}
void PutsList(int* list,int m,int n)
{
	int i,j;
	for(i = 0;i < m;i++)
	{
		for(j = 0;j < n;j++)
		{
			printf("%d ",*(list+i*n+j));
		}
		puts("");
	}
	return; 	
}
void PutsAList(AList ls)
{
	int i,j;
	for(i = 0;i < ls.m;i++)
	{
		//printf("alist[%d][0]=%d\n",i,alist[i][0]);
		printf("[");
		for(j = 1;j <= (ls.alist)[i][0];j++)
		{
			if(j == 1)
			{
				printf("%d",(ls.alist)[i][j]);
				continue;
			}
			printf(",%d",(ls.alist)[i][j]);
		}
		printf("]\n");
	}
	return; 
}
void getSymbolList(AList* pls,int* list)
{
	int tt;
	int co = 0;
	int i,j;
	for(i = 0;i < pls->m;i++)
	{
		for(co = 0,tt = i,j = pls->n-1;j >= 0;j--)
		{
			if(tt != 0)
			{
				(*(list+i*pls->n+j)) = tt % 2;
				tt = tt / 2;	
				if(*(list+i*pls->n+j) == 1)
				{
					co++;
				}
			}
			else
			{
				*(list+i*pls->n+j) = 0;
			}
		}
		(pls->alist)[i] = (int*)malloc(sizeof(int)*co+1);
		(pls->alist)[i][0] = co;
		//printf("alist[%d][0]=%d\n",i,alist[i][0]);
	}
	return; 
}
void getAList(AList* pls,int* list,int* A,void (*getSymbolList)(AList* pls,int* list))
{
	int i,j,k;
	getSymbolList(pls,list);
	for(i = 0;i < pls->m;i++)
	{
		for(k = 1,j = 0;j <pls->n;j++)
		{
			if(*(list+i*pls->n+j) == 1)
			{
				(pls->alist)[i][k++] = A[j];
			}
		}
	}
	return; 
}
 
int main()
{
	int n;
	puts("输入集合元素个数：");
	scanf("%d",&n);
	int A[n];//集合A，元素个数n，C99 
	for(int i = 0;i < n;i++)
	{
		scanf("%d",&A[i]);
	}
 
	int m = pow(2,n);
	int list[m][n];
 
	AList ls;
	ls.InitAList = InitAList;
	ls.InitAList(&ls,m,n);
	
	puts("\n生成【子集组合标记】与【全部子集】！");
	getAList(&ls,(int*)list,A,getSymbolList);
 
	puts("\n输出检查【子集组合标记】：");
	PutsList((int*)list,m,n);//输出二维【子集组合标记】数组list 
	 
	puts("\n输出检查【全部子集】：");
	PutsAList(ls);//输出生成【全部子集】，子集保存在列表ls中 
	
	close(&ls);//关闭列表ls，释放ls.InitAList(&ls,m,n)所分配的列表空间 
 
	return 0;
}